package com.spodrum.balloongl;

import java.util.Iterator;
import java.util.Random;

import org.andengine.engine.camera.Camera;
import org.andengine.engine.handler.IUpdateHandler;
import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.FillResolutionPolicy;
import org.andengine.entity.IEntityFactory;
import org.andengine.entity.particle.ParticleSystem;
import org.andengine.entity.particle.emitter.PointParticleEmitter;
import org.andengine.entity.particle.initializer.AlphaParticleInitializer;
import org.andengine.entity.particle.initializer.ColorParticleInitializer;
import org.andengine.entity.particle.initializer.RotationParticleInitializer;
import org.andengine.entity.particle.initializer.VelocityParticleInitializer;
import org.andengine.entity.particle.modifier.AlphaParticleModifier;
import org.andengine.entity.particle.modifier.ExpireParticleInitializer;
import org.andengine.entity.particle.modifier.RotationParticleModifier;
import org.andengine.entity.particle.modifier.ScaleParticleModifier;
import org.andengine.entity.scene.IOnSceneTouchListener;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.SpriteBackground;
import org.andengine.entity.sprite.Sprite;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.ui.activity.BaseGameActivity;

public class BalloonGLGameActivity extends BaseGameActivity 
{
	public static BalloonGLGameActivity instance;
	private static final Random RNG = new Random();

	private Camera camera;
	private static final int CAMERA_WIDTH = 480;
	private static final int CAMERA_HEIGHT = 720;

	//States
	public static final int STATE_PAUSE = 1;
	public static final int STATE_MENU = 2;
	public static final int STATE_INGAME = 3;
	public static final int STATE_WIN = 4;

	private int current_state = STATE_MENU;

	//Scenes
	private Scene splashScene;
	private Scene menuScene;
	private Scene gameScene;

	//
	private BalloonManager balloonManager;

	//Images
	private BitmapTextureAtlas splashTextureAtlas;
	private ITextureRegion splashTextureRegion;
	private Sprite splash;

	private BitmapTextureAtlas mBackgroundTexture;
	private ITextureRegion mBackgroundTextureRegion;

	private BitmapTextureAtlas mBalloonTitleTexture;
	private ITextureRegion mBalloonTitleTextureRegion;

	private BitmapTextureAtlas mBalloonTexture;
	private ITextureRegion mBalloonTextureRegion;
	
	private BitmapTextureAtlas mSpark1Texture;
	private ITextureRegion mSpark1TextureRegion;
	
	private BitmapTextureAtlas mSpark2Texture;
	private ITextureRegion mSpark2TextureRegion;
	
	private BitmapTextureAtlas mSpark3Texture;
	private ITextureRegion mSpark3TextureRegion;
	
	private ITextureRegion[] mSparksTextureRegions = new ITextureRegion[3];

	public static BalloonGLGameActivity getInstance() 
	{
		return instance;
	}

	@Override
	public EngineOptions onCreateEngineOptions() 
	{
		instance = this;

		camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
		EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.PORTRAIT_FIXED, 
				new FillResolutionPolicy(), camera);
		return engineOptions;
	}

	@Override
	public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception 
	{
		BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
		splashTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 180, 190, TextureOptions.DEFAULT);
		splashTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(splashTextureAtlas, this, "balloonsplash.png", 0, 0);
		splashTextureAtlas.load();

		pOnCreateResourcesCallback.onCreateResourcesFinished();
	}

	@Override
	public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception
	{
		splashScene = new Scene();
		splash = new Sprite(0, 0, splashTextureRegion, mEngine.getVertexBufferObjectManager());
		splash.setScale(1.5f);
		splash.setPosition((CAMERA_WIDTH - splash.getWidth()) * 0.5f, (CAMERA_HEIGHT - splash.getHeight()) * 0.5f);
		splashScene.attachChild(splash);
		pOnCreateSceneCallback.onCreateSceneFinished(this.splashScene);
	}

	@Override
	public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception
	{
		mEngine.registerUpdateHandler(new TimerHandler(3f, new ITimerCallback() 
		{
			public void onTimePassed(final TimerHandler pTimerHandler) 
			{
				mEngine.unregisterUpdateHandler(pTimerHandler);
				loadResources();
				loadScenes();         
				splashScene.detachSelf();
				mEngine.setScene(menuScene);

			}
		}));

		pOnPopulateSceneCallback.onPopulateSceneFinished();
	}

	private void loadResources()
	{
		this.mBackgroundTexture = new BitmapTextureAtlas(this.getTextureManager(), 480, 800);
		this.mBackgroundTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBackgroundTexture, this, "background.png", 0, 0);
		this.mBackgroundTexture.load();

		this.mBalloonTitleTexture = new BitmapTextureAtlas(this.getTextureManager(), 200, 59);
		this.mBalloonTitleTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBalloonTitleTexture, this, "balloon_title.png", 0, 0);
		this.mBalloonTitleTexture.load();

		this.mBalloonTexture = new BitmapTextureAtlas(this.getTextureManager(), 100, 126);
		this.mBalloonTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBalloonTexture, this, "balloon.png", 0, 0);
		this.mBalloonTexture.load();
		
		this.mSpark1Texture = new BitmapTextureAtlas(this.getTextureManager(),20, 20);
		this.mSpark1TextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mSpark1Texture, this, "spark1.png", 0, 0);
		this.mSpark1Texture.load();
		
		this.mSpark2Texture = new BitmapTextureAtlas(this.getTextureManager(), 20, 20);
		this.mSpark2TextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mSpark2Texture, this, "spark2.png", 0, 0);
		this.mSpark2Texture.load();
		
		this.mSpark3Texture = new BitmapTextureAtlas(this.getTextureManager(), 20, 20);
		this.mSpark3TextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mSpark3Texture, this, "spark3.png", 0, 0);
		this.mSpark3Texture.load();
		
		mSparksTextureRegions[0] = this.mSpark1TextureRegion;
		mSparksTextureRegions[1] = this.mSpark2TextureRegion;
		mSparksTextureRegions[2] = this.mSpark3TextureRegion;
	}

	private void loadScenes()
	{
		// load your game here, you scenes
		Sprite bgSprite = new Sprite(0, 0, this.mBackgroundTextureRegion, this.getVertexBufferObjectManager());
		SpriteBackground spriteBg = new SpriteBackground(bgSprite);

		float imageRatio = this.mBalloonTitleTextureRegion.getWidth()/this.mBalloonTitleTextureRegion.getHeight();
		float screenRatio = camera.getWidth()/camera.getHeight();
		float scaledWidth, scaledHeight;

		if(imageRatio <= screenRatio) 
		{
			// The scaled size is based on the height
			scaledHeight = camera.getHeight();
			scaledWidth = scaledHeight * imageRatio;
		} else 
		{
			// The scaled size is based on the width
			scaledWidth = camera.getWidth();
			scaledHeight = scaledWidth / imageRatio;
		}   
		Sprite balloonTitleSprite = new Sprite(0, camera.getHeight()/4, this.mBalloonTitleTextureRegion, this.getVertexBufferObjectManager());
		balloonTitleSprite.setSize(scaledWidth, scaledHeight);

		this.menuScene = new Scene();
		this.menuScene.setBackground(spriteBg);	
		this.menuScene.attachChild(balloonTitleSprite);
		this.menuScene.setOnSceneTouchListener(new IOnSceneTouchListener() {
			@Override
			public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) 
			{
				current_state = STATE_INGAME;
				menuScene.detachSelf();
				mEngine.setScene(gameScene);
				return true;
			}
		});

		this.gameScene = new Scene();
		this.gameScene.setBackground(spriteBg);

		balloonManager = new BalloonManager(camera.getWidth(), camera.getHeight(), this.mBalloonTextureRegion);
		this.gameScene.attachChild(balloonManager);
		this.gameScene.registerUpdateHandler(new IUpdateHandler() 
		{
			@Override
			public void onUpdate(final float pSecondsElapsed) 
			{
				if(balloonManager.getBalloons().size() == 0 )
					balloonManager.initBalloons();

				Iterator<Balloon> bIt = balloonManager.getBalloonIterator();
				while (bIt.hasNext()) 
				{
					Balloon b = bIt.next();
					if(b.getY() > camera.getHeight())
					{
						balloonManager.popBalloon(b);
						bIt.remove();
					}
				}
			}

			@Override
			public void reset() {}
		});

		this.gameScene.setOnSceneTouchListener(new IOnSceneTouchListener() {
			@Override
			public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) 
			{
				Iterator<Balloon> bIt = balloonManager.getBalloonIterator();
				while (bIt.hasNext()) 
				{
					Balloon b = bIt.next();
					if(b.contains(pSceneTouchEvent.getX(), pSceneTouchEvent.getY()))
					{
						balloonManager.popBalloon(b);
						bIt.remove();
						createPop(b);
					}
				}

				return true;
			}
		});
	}
	
	private void createPop(Balloon balloon)
	{
		PointParticleEmitter pointParticleEmitter = new PointParticleEmitter(balloon.getX(), balloon.getY());
		
		final ParticleSystem<Sprite> spriteParticleSystem = new ParticleSystem<Sprite>(new IEntityFactory<Sprite>() {

			@Override
			public Sprite create(float pX, float pY) 
			{
				Sprite sprite = new Sprite(pX, pY, mSparksTextureRegions[RNG.nextInt(2)], mEngine.getVertexBufferObjectManager());
				return sprite;
			}
		},pointParticleEmitter, 10, 10, 10);
		
		spriteParticleSystem.addParticleInitializer(new ColorParticleInitializer<Sprite>(balloon.getColor()));
		spriteParticleSystem.addParticleInitializer(new VelocityParticleInitializer<Sprite>(-20, 20, -20, 20));
		spriteParticleSystem.addParticleInitializer(new RotationParticleInitializer<Sprite>(0.0f, 360.0f));	
		
		spriteParticleSystem.addParticleModifier(new RotationParticleModifier<Sprite>(0, 5, 0.0f, 360.0f));
		spriteParticleSystem.addParticleModifier(new AlphaParticleModifier<Sprite>(0, 5, 1.0f, 0.0f));
				
		this.gameScene.attachChild(spriteParticleSystem);
		this.gameScene.registerUpdateHandler(new TimerHandler(6.0f, new ITimerCallback() 
		{	
			@Override
			public void onTimePassed(TimerHandler pTimerHandler) 
			{
				spriteParticleSystem.getParent().unregisterUpdateHandler(pTimerHandler);
				spriteParticleSystem.detachSelf();
			}
		}));
	}
}
